// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: date_test.cpp 228 2008-09-15 13:35:23Z heavyzheng $
//

#include <zzheng/quant/dates/quant_dates_test_cases.hpp>
#include <zzheng/quant/dates.hpp>
#include <zzheng/test_logging.hpp>

#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <utility>


namespace zzheng {
namespace test {

    namespace {

        void test_excel_day() {
            info("Running test case: test_excel_day");
            typedef std::vector<std::pair<int, quant::date> > date_assertions;
            date_assertions to_check;
            // TODO: to_check.push_back( std::make_pair(   -1, quant::date(1899, 12, 30)) );
            // TODO: to_check.push_back( std::make_pair(    0, quant::date(1899, 12, 31)) );
            to_check.push_back( std::make_pair(    1, quant::date(1899, 12, 31)) );
            to_check.push_back( std::make_pair(   60, quant::date(1900,  2, 28)) );
            to_check.push_back( std::make_pair(   61, quant::date(1900,  3,  1)) );
            to_check.push_back( std::make_pair(28891, quant::date(1979,  2,  5)) );
            to_check.push_back( std::make_pair(36525, quant::date(1999, 12, 31)) );
            to_check.push_back( std::make_pair(36526, quant::date(2000,  1,  1)) );
            to_check.push_back( std::make_pair(38869, quant::date(2006,  6,  1)) );
            to_check.push_back( std::make_pair(39507, quant::date(2008,  2, 29)) );
            to_check.push_back( std::make_pair(40968, quant::date(2012,  2, 29)) );
            to_check.push_back( std::make_pair(42429, quant::date(2016,  2, 29)) );
            for (date_assertions::const_iterator i = to_check.begin(); i != to_check.end(); ++i) {
                BOOST_CHECK_EQUAL(quant::create_from_excel_day(i->first), i->second);
                BOOST_CHECK_EQUAL(quant::get_excel_day(i->second), i->first);
            }
        }

        void test_swap_dates() {
            info("Running test case: test_swap_dates");
            const int EXCEL_DAY_1 = 30000;
            const int EXCEL_DAY_2 = 40000;
            quant::date d1 = quant::create_from_excel_day(EXCEL_DAY_1);
            quant::date d2 = quant::create_from_excel_day(EXCEL_DAY_2);
            BOOST_CHECK_NO_THROW(d1.swap(d2));
            BOOST_CHECK_EQUAL(quant::get_excel_day(d1), EXCEL_DAY_2);
            BOOST_CHECK_EQUAL(quant::get_excel_day(d2), EXCEL_DAY_1);
        }

        //! Tests that quant::parse_date() throws a quant::date_error when parsing an invalid date
        //! string.
        void test_parse_invalid_string_to_date() {
            info("Running test case: test_parse_invalid_string_to_date");
            BOOST_CHECK_THROW( quant::parse_date(""),            quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("12345-01-01"), quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-13-01"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-123-01"), quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-01-32"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-02-29"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-03-100"), quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("2006-04-31"),  quant::date_error );
            BOOST_CHECK_THROW( quant::parse_date("hello world"), quant::date_error );
        }

        //! Tests that quant::parse_date() can parse a valid date string to date.
        void test_parse_valid_string_to_date() {
            info("Running test case: test_parse_valid_string_to_date");
            for (int excel_day = 28891; excel_day < 30000; excel_day += 10) {
                quant::date d1 = quant::create_from_excel_day(excel_day);
                quant::date d2;
                BOOST_CHECK_NO_THROW( d2 = quant::parse_date(d1.str()) );
                BOOST_CHECK_EQUAL(d1, d2);
            }
        }


    } // anonymous namespace

    ////////////////////////////////////////////////////////////////////////////////////////////////

    void add_date_test_cases(boost::unit_test::test_suite& suite) {
        suite.add( BOOST_TEST_CASE(&test_excel_day) );
        suite.add( BOOST_TEST_CASE(&test_swap_dates) );
        suite.add( BOOST_TEST_CASE(&test_parse_invalid_string_to_date) );
        suite.add( BOOST_TEST_CASE(&test_parse_valid_string_to_date) );
    }

} // namespace zzheng::test
} // namespace zzheng




